﻿/*
Author : Onur "Xtro" ER
Create date : 20.05.2009
Last update : 29.06.2010
*/

using System;
using System.Runtime.InteropServices;

namespace Xtro.Gerecler
{
    // ReSharper disable InconsistentNaming
    public static class MessageBox
    // ReSharper restore InconsistentNaming
    {
        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        public delegate void OReport(string Text, uint UserData);

        public enum NOptions : uint
        {
            RightJustifyButtons = 0x0001,
            VistaStyle = 0x0002,
            Narrow = 0x0004
        }

        [Flags]
        public enum NFlags : uint
        {
            Ok = 0x0,
            OkCancel = 0x1,
            AbortRetryIgnore = 0x2,
            YesNoCancel = 0x3,
            YesNo = 0x4,
            RetryCancel = 0x5,
            CancelTryContinue = 0x6,
            ContinueAbort = 0x7,
            SkipSkipAllCancel = 0x8,
            IgnoreIgnoreAllCancel = 0x9,
            DoNotAskAgain = 0x01000000,
            DoNotTellAgain = 0x02000000,
            DoNotShowAgain = 0x04000000,
            YesToAll = 0x08000000,
            NoToAll = 0x10000000,
            Help = 0x00004000,

            DefaultButton2 = 0x00000100,
            DefaultButton3 = 0x00000200,
            DefaultButton4 = 0x00000300,
            DefaultButton5 = 0x00000400,
            DefaultButton6 = 0x00000500,

            IconHand = 0x00000010,
            IconQuestion = 0x00000020,
            IconExclamation = 0x00000030,
            IconAsteriks = 0x00000040,
            IconWarning = IconExclamation,
            IconError = IconHand,
            IconInformation = IconAsteriks,
            IconStop = IconHand,

            NoResource = 0x20000000, // do not try to load button strings from resources
            NoSound = 0x40000000, // do not play sound when mb is displayed
            SystemModal = 0x00001000,
            TopMost = 0x00040000,
            SetForeGround = 0x00010000
        }

        public enum NDialogResult : uint
        {
            Ok = 1,
            Cancel = 2,
            Abort = 3,
            Retry = 4,
            Ignore = 5,
            Yes = 6,
            No = 7,
            TryAgain = 10,
            Continue = 11,
            Skip = 14,
            SkipAll = 15,
            IgnoreAll = 16,
            YesToAll = 19,
            NoToAll = 20,
            Custom1 = 23,
            Custom2 = 24,
            Custom3 = 25,
            Custom4 = 26,
            DoNotAskAgain = 0x01000000,
            DoNotTellAgain = 0x02000000,
            DoNotShowAgain = 0x04000000,
            TimeOut = 0x80000000, // returned if timeout expired
            Help = 44,
            Report = 45
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct SUserDefinedButtonCaptions
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Abort;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Cancel;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Continue;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string DoNotAskAgain;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string DoNotTellAgain;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string DoNotShowAgain;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Help;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Ignore;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string IgnoreAll;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string No;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string NoToAll;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Ok;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Report;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Retry;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Skip;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string SkipAll;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string TryAgain;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string Yes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string YesToAll;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct SParameters
        {
            public uint HelpId; // help context ID for message.  0 indicates the application’s default Help context will be used
            public int TimeoutSeconds; // number of seconds before the default button will be selected
            public bool HideDisabledCounter;
            public int DisabledSeconds;
            public int X;
            public int Y;
            public NOptions Options;
            private IntPtr InstanceStrings; // Obsolote // if specified, will be used to load strings
            private IntPtr InstanceIcon; // Obsolote // if specified, will be used to load custom icon
            public IntPtr IconHandle;
            private uint IconResourceId; // Obsolote
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            private string IconName; // Obsolote
            private uint CustomButtonsResourceId; // Obsolote
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string CustomButtons; // "Custom 1\nCustom 2\nCustom 3\nCustom 4"
            private uint ReportButtonResourceId; // Obsolote
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            private string ReportButtonCaption; // Obsolote
            public string ModuleName; // for saving DoNotAsk state
            public int LineNo; // for saving DoNotAsk state
            public uint TextColor; // 0xFFFFFFFF = Default text color
            public uint BackColor; // 0xFFFFFFFF = Default back color
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaximumPath)]
            public string CompanyName; // for saving DoNotAsk state
            public uint ReportUserData; // data sent to report callback function
            public OReport OnReport; // report function
            private bool UseUserDefinedButtonCaptions; // Obsolote // For not loading from resource but passing directly
            public SUserDefinedButtonCaptions UserDefinedButtonCaptions;
        }

        static MessageBox()
        {
            InstanceCount = 0;

            ResetParameters();
        }

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern bool GetDontSave();

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern void SetDontSave(bool Value);

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern bool GetDontEncode();

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern void SetDontEncode(bool Value);

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern bool GetUseIniFile();

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern void SetUseIniFile(bool Value);

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern string GetIniFile();

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern void SetIniFile(string Name);

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern string GetRegistryKey();

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode)]
        static extern void SetRegistryKey(string Name);

        [DllImport("XMessageBox.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
        static extern int XMessageBox(IntPtr WindowHandle, string Text, string Caption, NFlags Flags, ref SParameters Parameters);

        private const int MaximumPath = 260;

        public static SParameters Parameters;

        public static bool SaveCheckBox { get { return !GetDontSave(); } set { SetDontSave(!value); } }
        public static bool EncodingEnabled { get { return !GetDontEncode(); } set { SetDontEncode(!value); } }
        public static bool SaveToIniFile { get { return GetUseIniFile(); } set { SetUseIniFile(value); } }
        public static string IniFileName { get { return GetIniFile(); } set { SetIniFile(value); } }
        public static string RegistryKeyName { get { return GetRegistryKey(); } set { SetRegistryKey(value); } }

        public static int InstanceCount { get; private set; }

        public static void ResetParameters()
        {
            Parameters = new SParameters { BackColor = 0xFFFFFFFF, TextColor = 0xFFFFFFFF };
        }

        public static NDialogResult Show(string Text, string Caption, NFlags Flags, bool ResetParameters = true)
        {
            InstanceCount++;
            try
            {
                var OldButtonCaptions = Parameters.UserDefinedButtonCaptions;

                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Abort)) Parameters.UserDefinedButtonCaptions.Abort = ResourcesButton.Abort;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Cancel)) Parameters.UserDefinedButtonCaptions.Cancel = ResourcesButton.Cancel;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Continue)) Parameters.UserDefinedButtonCaptions.Continue = ResourcesButton.Continue;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.DoNotAskAgain)) Parameters.UserDefinedButtonCaptions.DoNotAskAgain = ResourcesButton.DoNotAskAgain;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.DoNotTellAgain)) Parameters.UserDefinedButtonCaptions.DoNotTellAgain = ResourcesButton.DoNotTellAgain;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.DoNotShowAgain)) Parameters.UserDefinedButtonCaptions.DoNotShowAgain = ResourcesButton.DoNotShowAgain;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Help)) Parameters.UserDefinedButtonCaptions.Help = ResourcesButton.Help;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Ignore)) Parameters.UserDefinedButtonCaptions.Ignore = ResourcesButton.Ignore;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.IgnoreAll)) Parameters.UserDefinedButtonCaptions.IgnoreAll = ResourcesButton.IgnoreAll;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.No)) Parameters.UserDefinedButtonCaptions.No = ResourcesButton.No;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.NoToAll)) Parameters.UserDefinedButtonCaptions.NoToAll = ResourcesButton.NoToAll;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Ok)) Parameters.UserDefinedButtonCaptions.Ok = ResourcesButton.Ok;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Report)) Parameters.UserDefinedButtonCaptions.Report = ResourcesButton.Report;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Retry)) Parameters.UserDefinedButtonCaptions.Retry = ResourcesButton.Retry;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Skip)) Parameters.UserDefinedButtonCaptions.Skip = ResourcesButton.Skip;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.SkipAll)) Parameters.UserDefinedButtonCaptions.SkipAll = ResourcesButton.SkipAll;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.TryAgain)) Parameters.UserDefinedButtonCaptions.TryAgain = ResourcesButton.TryAgain;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.Yes)) Parameters.UserDefinedButtonCaptions.Yes = ResourcesButton.Yes;
                if (string.IsNullOrEmpty(Parameters.UserDefinedButtonCaptions.YesToAll)) Parameters.UserDefinedButtonCaptions.YesToAll = ResourcesButton.YesToAll;

                var Result = (NDialogResult)XMessageBox(IntPtr.Zero, Text, Caption, Flags, ref Parameters);

                Parameters.UserDefinedButtonCaptions = OldButtonCaptions;

                if (ResetParameters) MessageBox.ResetParameters();

                return Result;
            }
            finally { InstanceCount--; }
        }
    }
}